#ifndef GAPHICS_AXIS_ALIGNED_BOUNDING_BOX_H
#define GAPHICS_AXIS_ALIGNED_BOUNDING_BOX_H

#include "boost/scoped_array.hpp"

#include "graphics/basic.h"
#include "graphics/bounding_volume.h"

namespace graphics{

class AxisAlignedBoundingBox : public BoundingVolume{
public:
    AxisAlignedBoundingBox(const Vector3 & center) : min_(center), max_(center), center_(center) {}    
    AxisAlignedBoundingBox(const boost::scoped_array<Vector3> & points, const int & point_count) { AddPoint(points, point_count); }    
    AxisAlignedBoundingBox(const Vector3 & min, const Vector3 & max) : center_((min + max)/2), min_(min), max_(max){}
    
    void AddPoint(const Vector3 & point) {
        if(point[X] < min_[X]) min_[X] = point[X];
        else if(point[X] > max_[X]) max_[X] = point[X];

        if(point[Y] < min_[Y]) min_[Y] = point[Y];
        else if(point[Y] > max_[Y]) max_[Y] = point[Y];
        
        if(point[Z] < min_[Z]) min_[Z] = point[Z];
        else if(point[Z] > max_[Z]) max_[Z] = point[Z];

        center_ = (min_ + max_) / 2;
    }

    void AddPoint(const boost::scoped_array<Vector3> & points, const int & point_count) {
        for(int i = 0; i < point_count; i++) {
            if(points[i][X] < min_[X]) min_[X] = points[i][X];
            else if(points[i][X] > max_[X]) max_[X] = points[i][X];

            if(points[i][Y] < min_[Y]) min_[Y] = points[i][Y];
            else if(points[i][Y] > max_[Y]) max_[Y] = points[i][Y];
            
            if(points[i][Z] < min_[Z]) min_[Z] = points[i][Z];
            else if(points[i][Z] > max_[Z]) max_[Z] = points[i][Z];
        }
        center_ = (min_ + max_) / 2;
    }
     
    bool Includes(const Vector3 &point) const {
        if(point[X] < min_[X] || point[X] > max_[X]) return false;
        else if(point[Y] < min_[Y] || point[Y] > max_[Y]) return false;
        else if(point[Z] < min_[Z] || point[Z] > max_[Z]) return false;
        else return true;
    }
     
    bool Overlaps(const BoundingVolume * other) const;
    bool OverlapWith(const AxisAlignedBoundingBox * other) const;
    bool OverlapWith(const OrientedBoundingBox * other) const;
    bool OverlapWith(const BoundingSphere * other) const ;

    const Vector3 GetDimension() const {return max_ - min_;}
    const Vector3 GetHalfDimension() const {return max_ - center_;}

    const Vector3 & GetCenter() const {return center_;}
    const Vector3 & GetMax() const {return max_;}
    const Vector3 & GetMin() const {return min_;}

private:
    Vector3 min_;
    Vector3 max_;
    Vector3 center_;    
};


}
#endif